$FORCE_SAVE=$false
$cwd = (Get-Item .).FullName

$uproject_file = Get-ChildItem . -Filter "*.uproject" | Select-Object -First 1
if ($null -eq $uproject_file) {
    Write-Host "uproject file not found."
    Exit -1
}

$uproject = $uproject_file | Get-Content -Raw | ConvertFrom-Json
$project_name = $uproject_file.BaseName
$engine_ver = $uproject.EngineAssociation
Write-Host "Project name is $project_name"
Write-Host "Project EngineVersion is ${engine_ver}"

$BuildSettingsVersion = "V2"
if ([float]$engine_ver -ge 5.3) {
	$BuildSettingsVersion = "V4"
}

$modules = @(
    @{
        "Name" = "$project_name"
        "Type" = "Runtime"
        "LoadingPhase" = "Default"
    }
)

if ($null -eq $uproject.Modules) {
    Write-Host "Modules field not exists."
    $uproject | Add-Member -Name "Modules" -Value $modules -MemberType NoteProperty
    Write-Host "Adding [Modules] field:",($uproject.Modules| ConvertTo-Json)
    <# save uproject file #>
    $uproject | ConvertTo-Json -Depth 3 | Out-File $uproject_file.FullName
}
else {
    <# Action when all if and elseif conditions are false #>
    $project_name = $uproject.Modules[0].Name
}


<# construct file path #>

# /Source/$project_name.Target.cs
[System.IO.FileInfo] $Target_cs_path=Join-Path (Join-Path $cwd -ChildPath "Source") -ChildPath "${project_name}.Target.cs"

# /Source/$project_nameEditor.Target.cs
[System.IO.FileInfo] $Editor_Target_cs_path=Join-Path (Join-Path $cwd -ChildPath "Source") -ChildPath "${project_name}Editor.Target.cs"

# /Source/$project_name/$project_name.Build.cs
[System.IO.FileInfo] $Build_cs_path=Join-Path (Join-Path $cwd -ChildPath "Source\${project_name}") -ChildPath "${project_name}.Build.cs"

# /Source/$project_name/$project_name.cpp
[System.IO.FileInfo] $cpp_path=Join-Path (Join-Path $cwd -ChildPath "Source\${project_name}") -ChildPath "${project_name}.cpp"

# /Source/$project_name/$project_name.h
[System.IO.FileInfo] $h_path=Join-Path (Join-Path $cwd -ChildPath "Source\${project_name}") -ChildPath "${project_name}.h"


<# construct file content #>

# /Source/$project_name.Target.cs
$Target_cs_content=@"
// Fill out your copyright notice in the Description page of Project Settings.

using UnrealBuildTool;
using System.Collections.Generic;

public class ${project_name}Target : TargetRules
{
	public ${project_name}Target(TargetInfo Target) : base(Target)
	{
		Type = TargetType.Game;
		DefaultBuildSettings = BuildSettingsVersion.${BuildSettingsVersion};

		ExtraModuleNames.AddRange( new string[] { "$project_name" } );
	}
}
"@

# /Source/$project_nameEditor.Target.cs
$Editor_Target_cs_content=@"
// Fill out your copyright notice in the Description page of Project Settings.

using UnrealBuildTool;
using System.Collections.Generic;

public class ${project_name}EditorTarget : TargetRules
{
	public ${project_name}EditorTarget(TargetInfo Target) : base(Target)
	{
		Type = TargetType.Editor;
		DefaultBuildSettings = BuildSettingsVersion.${BuildSettingsVersion};

		ExtraModuleNames.AddRange( new string[] { "$project_name" } );
	}
}
"@

# /Source/$project_name/$project_name.Build.cs
$Build_cs_content=@"
// Fill out your copyright notice in the Description page of Project Settings.

using UnrealBuildTool;

public class ${project_name} : ModuleRules
{
	public ${project_name}(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });

		PrivateDependencyModuleNames.AddRange(new string[] { });

		// Uncomment if you are using Slate UI
		// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

		// Uncomment if you are using online features
		// PrivateDependencyModuleNames.Add("OnlineSubsystem");

		// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
	}
}
"@

# /Source/$project_name/$project_name.cpp
$cpp_content=@"
// Fill out your copyright notice in the Description page of Project Settings.

#include "${project_name}.h"
#include "Modules/ModuleManager.h"

IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, ${project_name}, "${project_name}" );
"@

# /Source/$project_name/$project_name.h
$h_content=@"
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

"@



<# save files #>
$not_overwrite=!$FORCE_SAVE

# Create ./Source folder
New-Item -Path (Join-Path $cwd -ChildPath "Source\${project_name}") -ItemType Directory -Force

$Target_cs_content | Out-File -FilePath $Target_cs_path.FullName -Encoding utf8 -NoClobber:$not_overwrite

$Editor_Target_cs_content | Out-File -FilePath $Editor_Target_cs_path.FullName -Encoding utf8 -NoClobber:$not_overwrite

$Build_cs_content | Out-File -FilePath $Build_cs_path.FullName -Encoding utf8 -NoClobber:$not_overwrite

$cpp_content | Out-File -FilePath $cpp_path.FullName -Encoding utf8 -NoClobber:$not_overwrite

$h_content | Out-File -FilePath $h_path.FullName -Encoding utf8 -NoClobber:$not_overwrite